//
//  GoogleReader.m
//  jRSSReader
//
//  Created by Jodynek on 4/12/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "GoogleReader.h"

@implementation GoogleReader

- (void) login:(NSString *)user pass:(NSString *)password
{
  dateFormat = [[NSDateFormatter alloc] init];
  [dateFormat setDateFormat: @"yyyy-MM-dd'T'HH:mm:ss'Z'"]; // 2009-07-31T03:24:53Z
  stories = [[NSMutableArray alloc] init];      
  
  NSString *sAtomURL = @"http://www.google.com/reader/atom/?trans=false&n=50";
  NSString *gUserString = user;
  NSString *gPassString = password;
  NSString *GOOGLE_CLIENT_AUTH_URL = @"https://www.google.com/accounts/ClientLogin?client=jRSSReader";
  NSString *gSourceString = @"jRSSReader";
  
  //define our return objects
  BOOL authOK;
  NSString *authToken;
  NSString *authMessage = [[NSString alloc] init];
  //begin NSURLConnection prep:
  NSMutableURLRequest *httpReq = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:GOOGLE_CLIENT_AUTH_URL] ];
  [httpReq setTimeoutInterval:30.0];
  //[httpReq setCachePolicy:NSURLRequestReloadIgnoringCacheData];
  [httpReq setHTTPMethod:@"POST"];
  //set headers
  [httpReq addValue:@"Content-Type" forHTTPHeaderField:@"application/x-www-form-urlencoded"];
  //set post body
  NSString *requestBody = [[NSString alloc] 
                           initWithFormat:@"Email=%@&Passwd=%@&service=reader&accountType=HOSTED_OR_GOOGLE&source=%@",
                           gUserString, gPassString, [NSString stringWithFormat:@"%@", gSourceString]];
  
  [httpReq setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding]];
  
  NSHTTPURLResponse *response = nil;
  NSError *error = nil;
  NSData *data = nil;
  NSString *responseStr = nil;
  NSArray *responseLines = nil;
  NSString *errorString;
  //NSDictionary *dict;
  int responseStatus = 0;
  //this should be quick, and to keep same workflow, we'll do this sync.
  //this should also get us by without messing with threads and run loops on Tiger.
  data = [NSURLConnection sendSynchronousRequest:httpReq returningResponse:&response error:&error];
  
  if ([data length] > 0) {
    responseStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    //NSLog(@"Response From Google: %@", responseStr);
    
    // we must separate "Auth=" part of value
    NSArray *lines = [responseStr componentsSeparatedByString:@"\n"];
    NSMutableDictionary *token = [NSMutableDictionary dictionary];
    for(NSString *s in lines)
    { 
      NSArray *kvpair = [s componentsSeparatedByString:@"="];
      if([kvpair count]>1)
        [token setObject:[kvpair objectAtIndex:1] forKey:[kvpair objectAtIndex:0]];
    }
    authToken = [token objectForKey:@"Auth"];
    
    responseStatus = (int)[response statusCode];
    //if we got 200 authentication was successful
    if (responseStatus == 200 ) {
      authOK = TRUE;
      authMessage = @"Successfully authenticated with Google. You can now start viewing your unread feeds.";
    }
    //403 = authentication failed.
    else if (responseStatus == 403) {
      authOK = FALSE;
      //get Error code.
      responseLines  = [responseStr componentsSeparatedByString:@"\n"];
      //find the line with the error value:
      int i;
      for (i =0; i < [responseLines count]; i++ ) {
        if ([[responseLines objectAtIndex:i] rangeOfString:@"Error="].length != 0) {
          errorString = [responseLines objectAtIndex:i] ;
        }
      }
      
      errorString = [errorString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
      /*
       Official Google clientLogin Error Codes:
       Error Code Description
       BadAuthentication  The login request used a username or password that is not recognized.
       NotVerified    The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
       TermsNotAgreed The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
       CaptchaRequired    A CAPTCHA is required. (A response with this error code will also contain an image URL and a CAPTCHA token.)
       Unknown    The error is unknown or unspecified; the request contained invalid input or was malformed.
       AccountDeleted The user account has been deleted.
       AccountDisabled    The user account has been disabled.
       ServiceDisabled    The user's access to the specified service has been disabled. (The user account may still be valid.)
       ServiceUnavailable The service is not available; try again later.
       */
      
      if ([errorString  rangeOfString:@"BadAuthentication" ].length != 0) {
        authMessage = @"Please Check your Username and Password and try again.";
      }else if ([errorString  rangeOfString:@"NotVerified"].length != 0) {
        authMessage = @"This account has not been verified. You will need to access your Google account directly to resolve this";
      }else if ([errorString  rangeOfString:@"TermsNotAgreed" ].length != 0) {
        authMessage = @"You have not agreed to Google terms of use. You will need to access your Google account directly to resolve this";
      }else if ([errorString  rangeOfString:@"CaptchaRequired" ].length != 0) {
        authMessage = @"Google is requiring a CAPTCHA response to continue. Please complete the CAPTCHA challenge in your browser, and try authenticating again";
        //NSString *captchaURL = [responseStr substringFromIndex: [responseStr rangeOfString:@"CaptchaURL="].length]; 
        //either open the standard URL in a browser, or show a custom sheet with the image and send it back...
        //parse URL to append to GOOGLE_CAPTCHA_URL_PREFIX
        //but for now... just launch the standard URL.
        //[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:GOOGLE_CAPTCHA_STANDARD_UNLOCK_URL]];         
      }else if ([errorString  rangeOfString:@"Unknown" ].length != 0) {
        authMessage = @"An Unknow error has occurred; the request contained invalid input or was malformed.";
      }else if ([errorString  rangeOfString:@"AccountDeleted" ].length != 0) {
        authMessage = @"This user account previously has been deleted.";
      }else if ([errorString  rangeOfString:@"AccountDisabled" ].length != 0) {
        authMessage = @"This user account has been disabled.";
      }else if ([errorString  rangeOfString:@"ServiceDisabled" ].length != 0) {
        authMessage = @"Your access to the specified service has been disabled. Please try again later.";
      }else if ([errorString  rangeOfString:@"ServiceUnavailable" ].length != 0) {
        authMessage = @"The service is not available; please try again later.";
      }
      
    }//end 403 if
    
  }
  //check most likely: no internet connection error:
  if (error != nil) {
    authOK = FALSE;
    if ( [error domain]  == NSURLErrorDomain) {
      authMessage = @"Could not reach Google.com. Please check your Internet Connection";
    }else {
      //other error
      authMessage = [authMessage stringByAppendingFormat:@"Internal Error. Please contact notoptimal.net for further assistance. Error: %@", [error localizedDescription] ];
    }
  }
  
  NSURL *urlAccount = [NSURL URLWithString:sAtomURL];
  NSString* param = [NSString stringWithFormat:@"GoogleLogin auth=%@",authToken]; 
  NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:urlAccount];
  [req setHTTPMethod:@"GET"];
  [req addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  [req setValue:param forHTTPHeaderField: @"Authorization"];
  [req addValue:@"Authorization" forHTTPHeaderField:param];      
  NSHTTPURLResponse *res;
  NSError *err;
  NSData *xmlData = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&err];
  TBXML *tbxml = [[TBXML alloc] initWithXMLData:xmlData error:&error];
  // if an error occured, log it    
  if (error) 
  {
    NSLog(@"Error! %@ %@", [error localizedDescription], [error userInfo]);
  } else 
  {
    // If TBXML found a root node, process element and iterate all children
    if (tbxml.rootXMLElement)
    {
      TBXMLElement *element = tbxml.rootXMLElement;
      NSString *name = [TBXML elementName:element];            
      NSLog(@"%@", name);          
      [self traverseElement:tbxml.rootXMLElement];
      //[self traverseElement:element];
    }
  }        
}

- (void) traverseElement:(TBXMLElement *)element 
{
  do 
  {
    if (element->firstChild) 
      [self traverseElement:element->firstChild];
    
    NSString *currentElement = [TBXML elementName:element];
    // traverse key/value pairs
    /*
     NSString *value = [TBXML textForElement:element];            
     NSLog(@"%@ -> %@", [TBXML elementName:element], value);
     */
    if([currentElement isEqualToString:@"entry"])
    {
      TBXMLElement *idd = [TBXML childElementNamed:@"id" parentElement:element];
      TBXMLElement *title = [TBXML childElementNamed:@"title" parentElement:element];
      TBXMLElement *updated = [TBXML childElementNamed:@"updated" parentElement:element];
      TBXMLElement *summary = [TBXML childElementNamed:@"summary" parentElement:element];
      TBXMLElement *link = [TBXML childElementNamed:@"link" parentElement:element];
      TBXMLElement *cat = [TBXML childElementNamed:@"category" parentElement:element];
      currentFeed = [ParsedFeed new];
      [currentFeed setId: [TBXML textForElement:idd]];
      [currentFeed setTitle: [TBXML textForElement:title]];
      // attribut source - GR has 3 <category> tags, source is in the third
      cat = cat->nextSibling->nextSibling;
      TBXMLAttribute *attr = cat->firstAttribute;
      [currentFeed setSource: [TBXML attributeValue:attr]];
      [currentFeed setPubDate:[ dateFormat dateFromString: [TBXML textForElement:updated]]];
      [currentFeed setSummary : [ NSMutableString stringWithString:[TBXML textForElement:summary]]];

      [TBXML iterateAttributesOfElement:link withBlock:^(TBXMLAttribute *attribute, NSString *name, NSString *value) {
        // Display name and value of attribute to the log window
        NSLog(@"%@->%@ = %@",[TBXML elementName:link], name, value);
        if ([name isEqualToString:@"href"] && ![value isEqualToString:@""])
        {
          [currentFeed setLink: [ NSMutableString stringWithString:value]];
          return;
        }
      }];
       
      [stories addObject:currentFeed];
    }
  } while ((element = element->nextSibling));  
}

- (NSMutableArray *) getStories
{
  return stories;
}

@end
